package demo3;

//字符串的修改
public class Test {
    public static void main1(String[] args) {
        String s = "hello";
        s += "world";
        System.out.println(s); //打印hello world
    }
    //拼接测试
    public static void main2(String[] args) {
        long start = System.currentTimeMillis(); //开始计时
        String s = "";
        for(int i =0; i<10000; i++) {
            s += i; //对s空字符串拼接10000次
        }
        long end = System.currentTimeMillis();//结束计时
        System.out.println(end - start);//打印时间

        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");
        for (int i = 0; i < 10000; i++) {
            sbf.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);

        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder("");
        for (int i = 0; i < 10000; i++) {
            sbd.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
        //每次拼接时都会产生一个StringBuffer的对象，所以时间效率差别很大
    }
    //从汇编的角度来查看，每次拼接都会产生新对象，时间效率很低
    public static void main3(String[] args) {
        String str1 = "";
        //拼接时产生一个StringBuffer对象，先把原字符串放进去，然后再把要拼接的值放进去
        for (int i = 0; i < 100; i++) {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(str1);
            stringBuffer.append(i);
            str1 = stringBuffer.toString();//因为要把结果赋值给str，要转换类型
        }
        System.out.println(str1);
        //下面的代码和上面的代码是等价的
        String str2 = "";
        for (int i = 0; i < 100; i++) {
            str2 += i;
        }
        System.out.println(str2);
    }
    //对上面进行简化 -- 优先使用下面这种方式拼接
    public static void main4(String[] args) {
        String str = "";
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(str);
        for (int i = 0; i < 100; i++) {
            stringBuffer.append(i);
        }
        System.out.println(stringBuffer);
    }
    //StringBuilder和StringBuffer
    //只是两个类，可以表示字符串，但是不能用 '=' 赋值，需要用new调用构造方法
    public static void main5(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("hello");
        System.out.println(stringBuilder); //可以正常打印hello
        //可以用ToString转化为String类型
        String s = stringBuilder.toString();
        System.out.println(s);
        //逆置字符串
        stringBuilder.reverse();
        System.out.println(stringBuilder);

        //把String对象变为StringBuilder对象
        StringBuilder stringBuilder1 = new StringBuilder(s);
    }
    //两个有什么区别呢？在各自的append方法实现中，Buffer的还加了个synchronized关键字，这个单词的意思是同步的
    //应用于多线程以及并发情况下，类似数据库中事物的隔离性
    //①String的内容不可修改，其它两个可以修改
    //②StringBuffer与StringBuilder的大部分功能是相似的
    //③StringBuffer采用同步处理，属于线程安全操作，而StringBuilder未采用同步处理，属于线程不安全操作

    public static void main(String[] args) {
        String str1 = new String("ab"); //创建两个对象，ab一个，new一个
        String str2 = new String("a") + new String("b");
        //创建六个对象， a一个，b一个，然后new两个，由于是拼接，创建一个StringBuilder对象
        //然后要赋值给String对象用到ToString方法再生成一个String对象
    }
    //几个OJ题
    //①找第一个出现的字母的下标
    class Solution1 {
        public int firstUniqChar(String s){
            int[] count = new int[26]; //记录每个字母出现的次数
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i); //依次遍历获取每个下标对应的字母
                count[ch - 'a']++;
            }
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i);
                if(count[ch - 'a'] == 1){
                    return i;
                }
            }
            return -1;
        }
    }
    //②计算字符串最后一个单词的长度，单词之间用空格隔开
    class Solution2 {
        public int lastLengthOfWord(String word){
            int index = -1;
            for (int i = word.length() - 1 ; i >= 0 ; i--) {
                if(word.charAt(i) == ' '){
                    index = i;
                    break;
                }
            }
            return word.length() - 1 - index;
        }
    }
    //③检验字符串是否是回文串
    //有效的字符只有字母和数字字符，其他都不是，并且忽略大小写
    class Solution3{
        //先写一个函数判断是否是有效字符
        public boolean isEffective(char ch){
            if(Character.isLetter(ch) || Character.isDigit(ch)){
                return true;
            }
            return false;
            //return Character.isLetterOrDigit(ch); //判断四不是数字或者字母
        }
        public boolean isPalindrome(String s){
            s = s.toLowerCase(); //全部整体转为小写字母
            int left = 0,right = s.length() - 1;
            while(left < right){
                while(left < right || isEffective(s.charAt(left))){
                    left++;
                }
                while(left < right ||  isEffective(s.charAt(right))){
                    right--;
                }
                if(s.charAt(left) != s.charAt(right)){
                    return false;
                }
                left++;
                right--;
            }
            return true;
        }
    }
}
